home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 2.iso / STUTTGART / FROMUTS / UNIXLIB37B / src / unix / c / tty < prev    next >
Text File  |  1992-09-04  |  13KB  |  614 lines

  1. static char sccs_id[] = "@(#) tty.c 4.0 "__DATE__" HJR";
  2.  
  3. /* tty.c (c) Copyright 1990 H.Rogers */
  4.  
  5. /* SYS V tty device driver for RiscOS */
  6.  
  7. #include <signal.h>
  8. #include <string.h>
  9. #include <ctype.h>
  10. #include <errno.h>
  11. #include <stdlib.h>
  12.  
  13. #include "fcntl.h"
  14. #include "termio.h"
  15.  
  16. #include "sys/types.h"
  17. #include "sys/unix.h"
  18. #include "sys/dev.h"
  19. #include "sys/tty.h"
  20. #include "sys/os.h"
  21. #include "sys/param.h"
  22.  
  23. static struct tty *__t; /* current tty */
  24.  
  25. #define __ttyx(x)    /* increment cursor posn. by (x) */ \
  26.     (__t->sx += (x), \
  27.     __t->del[__t->cx = (__t->cx + 1) & (MAXPATHLEN - 1)] = (x))
  28.  
  29. static int __ttyicanon(void *buf,int nbyte,struct file *f);
  30. static int __ttyiraw(void *buf,int nbyte,struct file *f);
  31.  
  32. static int __ttyinput(int c,int iflag);
  33. static void __ttyecho(int c,int oflag,int lflag);
  34. static void __ttydel(int lflag);
  35. static void __ttytab(int oflag);
  36. static void __ttycr(int oflag);
  37. static void __ttynl(int oflag);
  38.  
  39. static char __ttybaud[0x10] = { 0,9,1,10,11,2,0,3,12,4,13,5,6,7,8,0 };
  40.  
  41. /* get console window size */
  42.  
  43. static void __tty_console_gwinsz(register struct winsize *w)
  44. {
  45. static int i[9] = { 132,134,135,133,128,130,129,131,-1 };
  46. int o[8];
  47. int r[10];
  48.  
  49. r[0] = (int)i; r[1] = (int)o; os_swi(0x31,r);
  50. w->ws_col = o[1] - o[0] + 1;
  51. w->ws_row = o[3] - o[2] + 1;
  52. w->ws_xpixel = o[5] - o[4] + 1;
  53. w->ws_ypixel = o[7] - o[6] + 1;
  54. }
  55.  
  56. /* set console window size */
  57.  
  58. static void __tty_console_swinsz(register struct winsize *w)
  59. {
  60. static int i[7] = { 132,135,128,131,4,5,-1 };
  61. int o[6];
  62. int r[10];
  63. register int j;
  64.  
  65. r[0] = (int)i; r[1] = (int)o; os_swi(0x31,r);
  66. os_vdu(28);
  67. os_vdu(o[0]);
  68. os_vdu(o[1] + w->ws_row - 1);
  69. os_vdu(o[0] + w->ws_col - 1);
  70. os_vdu(o[1]);
  71. os_vdu(24);
  72. j = o[2]; j <<= o[4]; os_vdu(j & 0xff); os_vdu(j>>8);
  73. j = o[3] - (w->ws_ypixel - 1); j <<= o[5]; os_vdu(j & 0xff); os_vdu(j>>8);
  74. j = o[2] +  w->ws_xpixel - 1;  j <<= o[4]; os_vdu(j & 0xff); os_vdu(j>>8);
  75. j = o[3]; j <<= o[5]; os_vdu(j & 0xff); os_vdu(j>>8);
  76. }
  77.  
  78. /* read console */
  79.  
  80. static void __tty_console_gterm(register struct termio *t)
  81. {
  82. int r[3];
  83.  
  84. os_byte(0xdc,0,0xff,r); t->c_cc[VINTR] = r[1];
  85. os_byte(0xe5,0,0xff,r); if (r[1])
  86.   t->c_lflag &= ~ISIG;
  87. else
  88.   t->c_lflag |= ISIG;
  89. }
  90.  
  91. /* set console */
  92.  
  93. static void __tty_console_sterm(register struct termio *t)
  94. {
  95. os_byte(0xdc,t->c_cc[VINTR],0,0);
  96. if (t->c_lflag & ISIG)
  97.   os_byte(0xe5,0,0,0);
  98. else
  99.   os_byte(0xe5,0xff,0,0);
  100. }
  101.  
  102. /* set RS423 */
  103.  
  104. static void __tty_423_sterm(register struct termio *t)
  105. {
  106. register int i,c;
  107. int r[10];
  108.  
  109. i = t->c_cflag & CIBAUD; i = i ? (i>>IBSHIFT) : (t->c_cflag & CBAUD);
  110. r[0] = 5; if (r[1] = __ttybaud[i]) os_swi(0x57,r);
  111. i = t->c_cflag & CBAUD;
  112. r[0] = 6; if (r[1] = __ttybaud[i]) os_swi(0x57,r);
  113. i = t->c_cflag;
  114. switch (i & CSIZE)
  115.   {
  116.   case CS5:
  117.     c = 3;
  118.     break;
  119.   case CS6:
  120.     c = 2;
  121.     break;
  122.   case CS7:
  123.     c = 1;
  124.     break;
  125.   case CS8:
  126.   default:
  127.     c = 0;
  128.     break;
  129.   }
  130. if (i & CSTOPB) c |= 0x04;
  131. if (i & PARENB)
  132.   {
  133.   c |= 0x08;
  134.   if (!(i & PARODD)) c |= 0x10;
  135.   }
  136. r[0] = 1; r[1] = c; os_swi(0x57,r);
  137. }
  138.  
  139. int __ttyopen(char *file,int mode,struct file *f)
  140. {
  141. struct tty *_t;
  142. int l;
  143.  
  144. switch (*(file + 5))
  145.   {
  146.   case 'c':    /* console */
  147.     _t = __u->tty + (l = TTY_CON);
  148.     __u->flag = (__u->flag & ~__U_TTY) | (TTY_CON<<__U_TTYSHIFT);
  149.     break;
  150.   case 'r':    /* rs423 */
  151.     _t = __u->tty + (l = TTY_423);
  152.     __u->flag = (__u->flag & ~__U_TTY) | (TTY_423<<__U_TTYSHIFT);
  153.     break;
  154.   case 't':    /* tty */
  155.     _t = __u->tty + (l = ((__u->flag & __U_TTY)>>__U_TTYSHIFT));
  156.     break;
  157.   default:
  158.     return(-1);
  159.     break;
  160.   }
  161.  
  162.   {
  163.   register struct termio *t = _t->t;
  164.  
  165.   t->c_iflag = BRKINT|ICRNL|IMAXBEL;
  166.   t->c_oflag = OPOST|ONLCR|XTABS;
  167.   if (l == TTY_CON)
  168.     t->c_cflag = B38400|CS8|CREAD|HUPCL|CLOCAL;
  169.   else if (l == TTY_423)
  170.     t->c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL;
  171.   t->c_lflag = ISIG|ICANON|ECHO;
  172.   t->c_line = 0;
  173.  
  174.     {
  175.     static char cc[NCC] = { CINTR,CQUIT,CERASE,CKILL,CEOF,CEOL,CEOL2,
  176.       CSWTCH,CSTART,CSTOP,CSUSP,0,CREPRINT,CDISCARD,CWERASE,CLNEXT };
  177.  
  178.     memcpy(t->c_cc,cc,NCC);
  179.     }
  180.  
  181.   if (l == TTY_CON)
  182.     __tty_console_gterm(t);    /* RS423 is set up later */
  183.   }
  184.  
  185.   {
  186.   register struct winsize *w = _t->w;
  187.  
  188.   if (l == TTY_CON)
  189.     __tty_console_gwinsz(w);
  190.   else if (l == TTY_423)
  191.     {
  192.     w->ws_col = 80;
  193.     w->ws_row = 25;
  194.     w->ws_xpixel = w->ws_ypixel = 0;
  195.     }
  196.   }
  197.  
  198. if (l == TTY_CON)
  199.   {
  200.   _t->out = os_vdu;
  201.   _t->in = os_get;
  202.   _t->scan = os_inkey;
  203.   _t->init = os_console;
  204.   _t->flush = os_keyflush;
  205.   }
  206. else if (l == TTY_423)
  207.   {
  208.   _t->out = os_423vdu;
  209.   _t->in = os_423get;
  210.   _t->scan = os_423inkey;
  211.   _t->init = os_423;
  212.   _t->flush = os_423flush;
  213.   }
  214.  
  215. _t->buf = _t->ptr = 0; _t->cnt = 0; _t->del = 0; _t->sx = _t->cx = 0;
  216.  
  217.   {
  218.   register int *r = f->r;
  219.  
  220.   r[0] = r[1] = r[2] = r[3] = r[4] = 0; r[5] = 0x33;
  221.   }
  222.  
  223. (*(_t->init))();
  224.  
  225. if (l == TTY_423)
  226.   __tty_423_sterm(_t->t);
  227.  
  228. return(l);
  229. }
  230.  
  231. int __ttyclose(int l,struct file *f)
  232. {
  233. register struct tty *_t;
  234.  
  235. _t = __u->tty + l;
  236.  
  237. if (_t->del) free(_t->del);
  238. if (_t->buf) free(_t->buf);
  239.  
  240. _t->buf = _t->ptr = 0; _t->cnt = 0; _t->del = 0; _t->sx = _t->cx = 0;
  241.  
  242. return(0);
  243. }
  244.  
  245.  
  246. int __ttyread(int l,void *buf,int nbyte,struct file *f)
  247. {
  248. __t = __u->tty + l;
  249.  
  250. if (!__t->del)
  251.   if (!(__t->del = malloc(MAXPATHLEN))) { errno = ENOMEM; return(-1); }
  252.  
  253. return((__t->t->c_lflag & ICANON) ? \
  254.     __ttyicanon(buf,nbyte,f) : \
  255.     __ttyiraw(buf,nbyte,f));
  256. }
  257.  
  258. static int __ttyicanon(void *buf,register int nbyte,struct file *f)
  259. {
  260. register int c,i;
  261. register char *s;
  262. register int nflag;
  263. register int iflag,oflag,lflag;
  264. register char *cc;
  265. int ceof,ceol,ceol2;
  266.  
  267. #define F_LNEXT     000001
  268. #define F_MAX        000002
  269. #define F_NDELAY    000004
  270.  
  271. if (!__t->buf)
  272.   {
  273.   if (!(__t->buf = malloc(MAXPATHLEN))) { errno = ENOMEM; return(-1); }
  274.   __t->cnt = 0; __t->ptr = __t->buf;
  275.   }
  276.  
  277. if (__t == __u->tty)
  278.   os_byte(0xe5,0xff,0,0);    /* disable SIGINT */
  279.  
  280. ret:
  281.  
  282. if (__t->cnt)
  283.   {
  284.   if (__t == __u->tty)
  285.     os_byte(0xe5,0,0,0);    /* re-enable SIGINT */
  286.  
  287.   i = (nbyte > __t->cnt) ? __t->cnt : nbyte;
  288.   memcpy(buf,__t->ptr,i);
  289.   __t->cnt -= i; __t->ptr += i;
  290.   return(i);
  291.   }
  292.  
  293. nflag = (f->oflag & O_NDELAY) ? F_NDELAY : 0;
  294. iflag = __t->t->c_iflag; oflag = __t->t->c_oflag; lflag = __t->t->c_lflag;
  295. cc = (char *)__t->t->c_cc;
  296.  
  297. ceof = cc[VEOF];
  298. if (!(ceol = cc[VEOL])) ceol--;
  299. if (!(ceol2 = cc[VEOL2])) ceol2--;
  300.  
  301. s = __t->ptr = __t->buf; __t->sx = __t->cx = 0; i = 0;
  302.  
  303. for (;;)
  304.   {
  305.   if (i < MAXPATHLEN) nflag &= ~F_MAX; else nflag |= F_MAX;
  306.   if (nflag & F_NDELAY) c = (*(__t->scan))(0); else c = (*(__t->in))();
  307.   if (c < 0) goto eol;
  308.   if (c == '\r' && iflag & IGNCR) continue;
  309.   c = __ttyinput(c,iflag);
  310.   if (!(nflag & F_LNEXT))
  311.     {
  312.     if (c == '\n' || c == ceof || c == ceol || c == ceol2)
  313.       goto eol;
  314.     if (c == cc[VLNEXT])
  315.       { nflag |= F_LNEXT; continue; }
  316.     if (c == cc[VERASE])
  317.       { if (i) { __ttydel(lflag); i--; } continue; }
  318.     if (c == cc[VWERASE])
  319.       { while (--i >= 0 && isspace(s[i])) __ttydel(lflag); i++;
  320.     while (--i >= 0 && !isspace(s[i])) __ttydel(lflag); i++; continue; }
  321.     if (c == cc[VKILL])
  322.       { while (--i >= 0) __ttydel(lflag); i++;
  323.     if (lflag & ECHOK) __ttynl(oflag); continue; }
  324.     if (c == cc[VREPRINT])
  325.       { register int j; __ttyecho(c,oflag,lflag); __ttynl(oflag);
  326.     if (!(oflag & ONLRET)) __ttycr(oflag);
  327.     for (j = 0; j < i; j++) __ttyecho(s[j],oflag,lflag); continue; }
  328.     if (lflag & ISIG)
  329.       {
  330.       if (c == cc[VINTR])
  331.     { raise(SIGINT); continue; }
  332.       if (c == cc[VQUIT])
  333.     { raise(SIGQUIT); continue; }
  334.       }
  335.     }
  336.   else
  337.     nflag &= ~F_LNEXT;
  338.   if (nflag & F_MAX)
  339.     { if (iflag & IMAXBEL) (*(__t->out))('\007'); }
  340.   else
  341.     { __ttyecho(c,oflag,lflag); s[i++] = c; }
  342.   }
  343.  
  344. eol:
  345.  
  346. if (c != cc[VEOF] && c >= 0)
  347.   { if (!(nflag & F_MAX)) { __ttyecho(c,oflag,lflag); s[i++] = c; } }
  348.  
  349. if (__t->cnt = i)
  350.   goto ret;
  351. else
  352.   {
  353.   if (__t == __u->tty)
  354.     os_byte(0xe5,0,0,0);    /* re-enable SIGINT */
  355.  
  356.   return(0);
  357.   }
  358.  
  359. #undef F_LNEXT
  360. #undef F_MAX
  361. #undef F_NDELAY
  362. }
  363.  
  364. static int __ttyiraw(void *buf,register int nbyte,struct file *f)
  365. {
  366. register int c,i;
  367. register char *s;
  368. register int nflag;
  369. register int iflag,oflag,lflag;
  370. register char *cc;
  371. register unsigned int vm,vt;
  372.  
  373. #define F_NSCAN     000001
  374.  
  375. nflag = 0;
  376. iflag = __t->t->c_iflag; oflag = __t->t->c_oflag; lflag = __t->t->c_lflag;
  377. cc = (char *)__t->t->c_cc;
  378.  
  379. if (f->oflag & O_NDELAY)
  380.   vm = vt = 0;
  381. else
  382.   {
  383.   vm = (cc[VMIN] && cc[VTIME]) ? 1 : cc[VMIN];
  384.   vt = cc[VTIME] * 10;
  385.   }
  386. if (cc[VMIN] && !cc[VTIME]) nbyte = vm,nflag |= F_NSCAN;
  387.  
  388. s = buf; i = 0;
  389.  
  390. while (i < nbyte)
  391.   {
  392.   if (nflag & F_NSCAN) c = (*(__t->in))(); else c = (*(__t->scan))(vt);
  393.   if (c < 0) { if (i >= vm) return(i); else continue; }
  394.   if (c == '\r' && iflag & IGNCR) continue;
  395.   c = __ttyinput(c,iflag);
  396.   if (lflag & ISIG)
  397.     {
  398.     if (c == cc[VINTR] && __t != __u->tty)
  399.       { raise(SIGINT); continue; }
  400.     if (c == cc[VQUIT])
  401.       { raise(SIGQUIT); continue; }
  402.     }
  403.   __ttyecho(c,oflag,lflag); s[i++] = c;
  404.   }
  405.  
  406. return(i);
  407.  
  408. #undef F_NSCAN
  409. }
  410.  
  411.  
  412. int __ttywrite(int l,void *buf,int nbyte,struct file *f)
  413. {
  414. register int i,c;
  415. register char *s;
  416. register int oflag,lflag;
  417. register char *cc;
  418. register int (*out)(int);
  419.  
  420. __t = __u->tty + l;
  421.  
  422. if (!__t->del)
  423.   if (!(__t->del = malloc(MAXPATHLEN))) { errno = ENOMEM; return(-1); }
  424.  
  425. oflag = __t->t->c_oflag; lflag = __t->t->c_lflag;
  426. cc = (char *)__t->t->c_cc;
  427. out = __t->out;
  428.  
  429. s = buf; i = 0;
  430.  
  431. while (i < nbyte)
  432.   {
  433.   c = s[i++];
  434.   if ((oflag & (OPOST|OLCUC)) == (OPOST|OLCUC))
  435.     if (isupper(c))
  436.       c = _tolower(c);
  437.   if (c == cc[VERASE])
  438.     __ttydel(lflag);
  439.   else if (c == '\t')
  440.     __ttytab(oflag);
  441.   else if (c == '\n')
  442.     __ttynl(oflag);
  443.   else if (c == '\r')
  444.     __ttycr(oflag);
  445.   else
  446.     { __ttyx(1); (*out)(c); }
  447.   }
  448.  
  449. return(nbyte);
  450. }
  451.  
  452.  
  453. static int __ttyinput(register int c,register int iflag)
  454. {
  455. if (iflag & ISTRIP) c &= 0x7f;
  456. if (iflag & IUCLC)
  457.   if (isupper(c)) c += ('a' - 'A');
  458. if (iflag & INLCR)
  459.   if (c == '\n') c = '\r';
  460. if (iflag & ICRNL)
  461.   if (c == '\r') c = '\n';
  462. return(c);
  463. }
  464.  
  465. static void __ttyecho(register int c,register int oflag,register int lflag)
  466. {
  467. if (!((lflag & ECHO) || ((c == '\n') && (lflag & ECHONL)))) return;
  468.  
  469. if (c == '\t')
  470.   __ttytab(oflag);
  471. else if (c == '\n')
  472.   __ttynl(oflag);
  473. else if (c == '\r')
  474.   __ttycr(oflag);
  475. else if (iscntrl(c))
  476.   {
  477.   __ttyx(2);
  478.   (*(__t->out))('^');
  479.   (*(__t->out))((c == 0x7f) ? '?' : (c + '@'));
  480.   }
  481. else
  482.   {
  483.   __ttyx(1);
  484.   (*(__t->out))(c);
  485.   }
  486. }
  487.  
  488. static void __ttydel(register int lflag)
  489. {
  490. register int x;
  491.  
  492. if (__t->sx)
  493.   { x = __t->del[__t->cx]; __t->cx = (__t->cx - 1) & (MAXPATHLEN - 1); }
  494. else
  495.   x = 1;
  496.  
  497. __t->sx = (__t->sx > x) ? (__t->sx - x) : 0;
  498.  
  499. if (lflag & ECHO)
  500.   {
  501.   if (lflag & ECHOE)
  502.     while (x--)
  503.      {
  504.      (*(__t->out))('\b');
  505.      (*(__t->out))(' ');
  506.      (*(__t->out))('\b');
  507.      }
  508.   else
  509.     while (x--)
  510.       (*(__t->out))('\177');
  511.   }
  512. }
  513.  
  514. static void __ttytab(register int oflag)
  515. {
  516. if ((oflag & (OPOST|XTABS)) == (OPOST|XTABS))
  517.   {
  518.   register int x;
  519.  
  520.   x = (8 - (__t->sx & 0x7));
  521.   __ttyx(x);
  522.   while (x--) (*(__t->out))(' ');
  523.   }
  524. else
  525.   {
  526.   __ttyx(1);
  527.   (*(__t->out))('\t');
  528.   }
  529. }
  530.  
  531. static void __ttycr(register int oflag)
  532. {
  533. __t->sx = 0;
  534. if ((oflag & (OPOST|OCRNL)) == (OPOST|OCRNL))
  535.   (*(__t->out))('\n');
  536. else if ((oflag & (OPOST|ONOCR)) != (OPOST|ONOCR))
  537.   (*(__t->out))('\r');
  538. }
  539.  
  540. static void __ttynl(register int oflag)
  541. {
  542. if (oflag & OPOST)
  543.   {
  544.   if (oflag & ONLCR)
  545.     if (__t->sx || !(oflag & ONOCR))
  546.       (*(__t->out))('\r');
  547.   if (oflag & (ONLCR|ONLRET))
  548.     __t->sx = 0;
  549.   }
  550. (*(__t->out))('\n');
  551. }
  552.  
  553.  
  554. long __ttylseek(int l,long lpos,int whence,struct file *f)
  555. { errno = ESPIPE; return(-1); }
  556.  
  557.  
  558. int __ttyioctl(int l,int request,void *arg,struct file *f)
  559. {
  560. register struct tty *_t = __u->tty + l;
  561.  
  562. if (request == TIOCGWINSZ || request == TIOCSWINSZ)
  563.   {
  564.   register struct winsize *w = _t->w;
  565.  
  566.   if (request == TIOCGWINSZ)
  567.     {
  568.     if (l == TTY_CON)
  569.       __tty_console_gwinsz(w);
  570.     memcpy(arg,w,sizeof(struct winsize));
  571.     }
  572.   else
  573.     {
  574.     memcpy(w,arg,sizeof(struct winsize));
  575.     if (l == TTY_CON)
  576.       __tty_console_swinsz(w);
  577.     }
  578.   }
  579. else
  580.   {
  581.   register struct termio *t = _t->t;
  582.  
  583.   if (request & TCDRAIN)
  584.     { _t->ptr = _t->buf; _t->cnt = 0; (*(_t->flush))(); }
  585.  
  586.   switch (request & ~TCDRAIN)
  587.     {
  588.     case TCGETA:
  589.       if (l == TTY_CON)
  590.     __tty_console_gterm(t);
  591.       memcpy(arg,t,sizeof(struct termio));
  592.       break;
  593.     case TCSETA:
  594.       memcpy(t,arg,sizeof(struct termio));
  595.       if (l == TTY_CON)
  596.     __tty_console_sterm(t);
  597.       else if (l == TTY_423)
  598.     __tty_423_sterm(t);
  599.       break;
  600.     case TCSBRK:
  601.       if (l == TTY_423 && !arg) os_423break(25);
  602.       break;
  603.     case 0:
  604.       break;
  605.     default:
  606.       errno = EINVAL;
  607.       return(-1);
  608.       break;
  609.     }
  610.   }
  611.  
  612. return(0);
  613. }
  614.